/*
		ServEngine framework library
		A library to fast develop JEE online applications
	
		Copyright 2008 José Ignacio de Córdoba Álvaro

		Licensed under the Apache License, Version 2.0 (the "License");
		you may not use this file except in compliance with the License.
		You may obtain a copy of the License at

				http://www.apache.org/licenses/LICENSE-2.0

		Unless required by applicable law or agreed to in writing, software
		distributed under the License is distributed on an "AS IS" BASIS,
		WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
		See the License for the specific language governing permissions and
		limitations under the License.
	
		Jose Ignacio de Cordoba Alvaro
		http://ignacio.decordoba.com
*/

package com.servengine.user;

import com.servengine.portal.Component;
import com.servengine.portal.Portal;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.ejb.TransactionAttribute;

import javax.ejb.TransactionAttributeType;

import javax.ejb.Stateless;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * UserManager session EJB encloses all business logic related tu user management.
 * @see UserManagerLocal
 */
@Stateless(name="UserManager")
public class UserManagerBean implements UserManagerLocal
{
	public static String USER_REQUIRES_SIGNUP_CONFIRMATION="user.requiressignupconfirmation"; // Propiedad para el portal
	//public static String USER_SIGNUP_CONFIRMATION_PENDING = "user.signupconfirmationpending"; // Propiedad para el usuario

	@PersistenceContext(unitName="mainPersistenceUnit")
	private EntityManager entityManager;

	private static org.apache.commons.logging.Log log=org.apache.commons.logging.LogFactory.getLog(UserManagerBean.class.getName());
	//	@EJB private MailRelayLocal mailrelay;

	protected String guestUserid="guest"; //TODO ¿Seguro que deben ser Static? Lo fijo por ahorrar.
	protected String adminUserid="admin";
	private String[] globalAdminUserids={ "admin" }; //TODO Pasar estas tres cosas a recursos

	/*
 * @PostConstruct
	public void ejbLoad()
	{
	  log.info("guestuserid=" + guestUserid + ", adminuserid=" + adminUserid + ", globaladminuserids=" + globalAdminUserids);
//		entityManager.setFlushMode(FlushModeType.AUTO);
	}*/

	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public UserSession getUserSession(String portalid, String userid, String password) throws javax.security.auth.login.FailedLoginException
	{
		if (userid==null)
			throw new javax.security.auth.login.FailedLoginException("error.emptyUserid");
		//			UserLocal userlocal = userlocalhome.findByUserid(portalid, userid.toLowerCase());
		User user=getUser(portalid, userid);
		if (user==null)
			throw new javax.security.auth.login.FailedLoginException("error.invalidUseridOrPassword");
		if (!user.checkEncodedPassword(password))
			throw new javax.security.auth.login.FailedLoginException("error.invalidUseridOrPassword");
		/*			if (userlocal.getRoles().size()==0 && !propertymanagerlocal.hasUserproperty(userlocal.getPkey(), USER_SIGNUP_CONFIRMATION_PENDING))
		{
			log.warn("User "+userlocal.getId()+"@"+userlocal.getPortal().getId()+" has no roles. Setting new user roles for this user.");
			setNewuserroles(userlocal);
		}*/
		UserSession usersession=new UserSession(user);
		user.setLastLogin(usersession.getStart());
		entityManager.persist(usersession);
		return usersession;
	}

	/**
	 * Devuelve un usuario para utilizarlo en una nueva sesión, partiendo de una antigua (para identificar el usuario). No solo devuelve el usuario sino que crea una entrada en UserSession y la asocia a ese usuario. Este método se usa en el proceso de autologin.
	 */
	public User getUserBySession(Integer userSessionId)
	{
		UserSession oldusersession=entityManager.find(UserSession.class, userSessionId);
		return getUser(oldusersession.getPortalid(), oldusersession.getUserid());
	}

	public UserSession getNewUserSession(String portalid, String oldUserSessionIdData)
	{
		Integer oldUserSessionId=new Integer(oldUserSessionIdData.split(",")[0]);
		UserSession oldusersession=entityManager.find(UserSession.class, oldUserSessionId);
		if (!portalid.equals(oldusersession.getPortalid()))
			throw new IllegalArgumentException();
		try
		{
			oldusersession.checkEncodedId(oldUserSessionIdData.split(",")[1]);
		} catch (IndexOutOfBoundsException e)
		{
			throw new IllegalArgumentException();
		}
		User user=getUser(oldusersession.getPortalid(), oldusersession.getUserid());
		if (isAdmin(user))
			log.warn("Admin user "+user.getUserid()+"@"+portalid+" loggedin via auto login");
		UserSession usersession=new UserSession(user);
		entityManager.persist(usersession);
		user.setLastLogin(usersession.getStart());
		return usersession;
	}

	/*	public boolean checkglobalaccess(UserLocal user)
	{
		return globaladminusers.contains(user);
	}

	public Collection getGlobalAdminEmails()
	{
		Iterator it = globaladminusers.iterator();
		ArrayList emails = new ArrayList();
		while (it.hasNext())
		{
			UserLocal u = (UserLocal)it.next();
			if (u.getEmail() != null && !u.getEmail().equals(""))
				emails.add(u.getEmail());
		}
		return emails;
	}*/

	/**
	 * Returns first admin's email (the first user with admin priviledges found in the query).
	 */
	public String[] getAdminEmails(String portalid)
	{
		ArrayList emails=new ArrayList();
		for (User user: getAdminUsers(portalid))
			emails.add(user.getEmail());
		if (emails.size()>9)
			return (String[])emails.toArray();
		log.warn("No admins in portal "+portalid);
		return new String[0];
	}

	public UserSession getGuestUserSession(String portalid)
	{
		Query query=entityManager.createNamedQuery("User.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", guestUserid);
		try
		{
			return new UserSession((User)query.getSingleResult());
		} catch (NoResultException e)
		{
			log.warn("No guest user in portal "+portalid);
			return new UserSession(new User(entityManager.find(Portal.class, portalid), "guest"));
		}
	}

	/**
	 * Returns all users in the portal as a Collection of UserSBean objects. If there are no users (¿?) returns an empty ArrayList. never returns null.
	 */
	public Collection<User> getUsers(String portalid)
	{
		//		return entityManager.find(Portal.class,portalid).getUsers();
		Query query=entityManager.createNamedQuery("User.findByPortalid");
		query.setParameter("portalid", portalid);
		return query.getResultList();
	}

	public Role getAdminRole(String portalid)
	{
		Query query=entityManager.createNamedQuery("Role.findByName");
		query.setParameter("portalid", portalid);
		query.setParameter("name", "admin"); //FIXME
		return (Role)query.getSingleResult();
	}

	public Collection<User> getAdminUsers(String portalid)
	{
		ArrayList<User> users=new ArrayList<User>();
		Role adminRole=getAdminRole(portalid);
		if (adminRole==null)
			log.warn("Portal "+portalid+" has no Admin role!!!");
		else
			for (User user: adminRole.getUsers())
				users.add(user);
		return users;
	}

	/*	protected Collection<UserSBean> getAdminUsers(String portalid) throws RemoteException,FinderException
	{
		Collection<Integer> rolepkeys = new ArrayList<Integer>();
		for (RoleSBean role: usermanager.getRoles(portalid))
			if (!role.getId().equals("user"))
				rolepkeys.add(role.getPkey());
		return usermanager.getUsersbyrolepkeys(portalid,rolepkeys);
	}*/


	/*	private void setRoles(UserLocal userlocal, Integer[] rolepkeys)// throws FinderException
	{
		String portalid=userlocal.getPortal().getId();
		Collection<RoleLocal> roles = new ArrayList<RoleLocal>();
	  if (rolepkeys != null)
	    for (Integer rolepkey: rolepkeys)
	      if (rolepkey != null)
	      {
	        RoleLocal role = rolelocalhome.findByPrimaryKey(rolepkey);
	        if (!role.getPortal().getId().equals(portalid))
	          throw new IllegalArgumentException();
	        roles.add(role);
	      }
	  userlocal.setRoles(roles);

	}*/

	public void persist(User user)
	{
		persist(user, null);
	}

	public void persist(User user, Map<String, String> extraUserdataMap)
	{
		if (user.getId()==null)
		{
			if (exists(user.getPortal().getId(), user.getUserid()))
				throw new IllegalArgumentException("userExists");
			entityManager.persist(user);
		} else
			entityManager.merge(user);
		if (extraUserdataMap!=null)
		{
			Set<ExtraUserdata> expurganda=new HashSet<ExtraUserdata>();
			expurganda.addAll(user.getExtraUserdata());
			user.getExtraUserdata().removeAll(expurganda); //Podemos hacer un set con un Set vacío.
			for (ExtraUserdata datum: expurganda)
				entityManager.remove(entityManager.find(ExtraUserdata.class, datum.getId())); //Por si está detached, que lo está seguro.
			for (ExtraUserdataField field: user.getPortal().getExtraUserdataFields())
				if (extraUserdataMap.keySet().contains(field.getName()))
				{
					ExtraUserdata datum=new ExtraUserdata(field, user, extraUserdataMap.get(field.getName()));
					entityManager.persist(datum);
					user.getExtraUserdata().add(datum);
				}
		}
		entityManager.flush();
	}

	public void setUserRoles(String portalid, Integer userId, Integer[] roleIds)
	{
	  User user=getUser(portalid, userId);
	  Set<Role> roles=new HashSet<Role>();
		if (roleIds!=null)
			for (Integer roleId: roleIds)
				if (roleId!=null)
					roles.add(getRole(portalid, roleId));
		user.setRoles(roles);
		entityManager.merge(user);
	}

	/*	public Integer storeUser(UserSBean user) throws CreateException, FinderException
	{
		try
		{
			UserLocal userlocal = null;
			if (user.getPkey() != null)
			{
				userlocal = userlocalhome.findByPrimaryKey(user.getPkey());
				setRoles(userlocal,user.getRolepkeys());
			} else
			{
				if (user.getPortal() == null)
					throw new CreateException("Can't create user with null portal");
				try
				{
					userlocalhome.findByUserid(user.getPortalid(),user.getUserid().toLowerCase());
					throw new CreateException("user.exists");
				} catch (FinderException e)
				{
					if (log.isDebugEnabled()) log.debug("Creating user "+user.getUserid()+"@"+user.getPortalid());
				}
				PortalLocal portal = portallocalhome.findByPrimaryKey(user.getPortalid());
				userlocal = userlocalhome.create(portal, user.getUserid().toLowerCase());
				
				if (user.getRolepkeys()==null || user.getRolepkeys().length==0)
				{
					if (!isRequiressignupconfirmation(user.getPortalid()))
						setNewuserroles(userlocal);
				} else
					setRoles(userlocal,user.getRolepkeys());
			}
			userlocal.setEmail(user.getEmail());
			userlocal.setFirstname(user.getFirstname());
			userlocal.setLastname(user.getLastname());
			userlocal.setLastname2(user.getLastname2());
			if (user.getNewpassword() != null && user.getNewpassword().length() > 0)
				userlocal.setEncodePassword(user.getNewpassword());
			//Extra user data
			try
			{
				Collection<ExtraUserdataLocal> expurganda = new ArrayList<ExtraUserdataLocal>();
				for (ExtraUserdataLocal datum: userlocal.getExtrauserdata())
					expurganda.add(datum);
			  for (ExtraUserdataLocal datum: expurganda)
					datum.remove();
			} catch (Exception e)
			{
				log.error(e.getMessage(), e); //Seguimos por no parar...
			}
			userlocal.setExtrauserdata(new ArrayList<ExtraUserdataLocal>());
			if (user.getExtrauserdata() != null && user.getExtrauserdata().size() > 0)
				for (Map.Entry<String,String> datum: user.getExtrauserdata().entrySet())
					try
					{
						extrauserdatalocalhome.create(userlocal, extrauserdatafieldlocalhome.findByFieldname(user.getPortalid(),datum.getKey()),datum.getValue());
					} catch (FinderException e)
					{
						log.error("No extra field "+datum.getKey()+" @ "+user.getPortalid());
					} catch (javax.ejb.DuplicateKeyException e)
					{
						log.error("For "+datum.getKey()+" @ "+user.getPortalid()+": "+e.getMessage());
					}
			// User properties
			if (user.getProperties() != null)
				try
				{
					propertymanagerlocal.storeUserproperties(userlocal.getPkey(), user.getProperties());
				} catch (RemoveException e)
				{
					throw new IllegalStateException(e.getMessage());
				}
			if (log.isDebugEnabled()) log.debug("User stored: " + userlocal.getPkey()+", "+userlocal.getId() + "@" + userlocal.getPortal().getId()+", "+userlocal.getRoles().size()+" roles");
			return userlocal.getPkey();
		} catch (FinderException e)
		{
			throw new EJBException(e); // To make CMT rollback this transaction
		}
	}*/

	public void userUnbound(Integer userSessionId)
	{
		entityManager.find(UserSession.class, userSessionId).setEnd(new java.util.Date());
	}

	public void setUserpassword(Integer userId, String password)
	{
		entityManager.find(User.class, userId).encodePassword(password);
	}

	public boolean isAdmin(User user)
	{
		return user.getRoles().contains(getAdminRole(user.getPortalid()));
	}

	public Set<Role> getNewUserRoles(String portalid)
	{
		Set<Role> roles=new HashSet<Role>();
		Query query=entityManager.createNamedQuery("Role.findNewUserRoles");
		query.setParameter("portalid", portalid);
		roles.addAll(query.getResultList());
		return roles;
	}

	public boolean exists(String portalid, String userid)
	{
		Query query=entityManager.createNamedQuery("User.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", userid.toLowerCase());
		try
		{
			query.getSingleResult();
			return true;
		} catch (NoResultException e)
		{
			return false;
		}
	}

	/*	public boolean checkglobalaccess(Integer userpkey)
	{
		try
		{
			UserLocal user = userlocalhome.findByPrimaryKey(userpkey);
			return checkglobalaccess(user);
		} catch (FinderException e)
		{
			return false;
		}
	}*/

	public void changeUserPassword(String portalid, String userid, String password)
	{
		Query query=entityManager.createNamedQuery("User.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", userid.toLowerCase());
		((User)query.getSingleResult()).encodePassword(password);
	}

	public void setUserpassword(String portalid, Integer userId, String password)
	{
		User user=entityManager.find(User.class, userId);
		if (!user.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException("Uffffffff... does that user really belong to your portal?");
		user.encodePassword(password);
	}

	/*	public String getUserEmail(String portalid, String userid) throws FinderException
	{
		if (portalid==null || userid==null)
			throw new IllegalArgumentException(userid+"@"+portalid);
		return userlocalhome.findByUserid(portalid, userid).getEmail();
	}*/

	/**
	 * Este es un "metodo de conveniencia" para cuando no se tiene el usuario instanciado por que es una bean de fuera de ServEngineEJB. El metodo devuelve el usuario instanciado por si la Bean lo necesita (generalmente si)
	 */
	public boolean checkaccess(String portalid, String userid, String classname)
	{
		Query query=entityManager.createNamedQuery("User.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", userid.toLowerCase());
		User user=(User)query.getSingleResult();
		if (user==null)
			return false;
		return checkAccess(user, classname);
	}

	public boolean checkActionAccess(User user, Component action)
	{
		if (user.getActionClassNames().contains(action.getClassName()))
			return true;
		/*for (Role role: user.getRoles()) // NO HACE FALTA, SE HACE AL CARGAR UN USUARIO CON setActionClassNames()
			if (action.getRoles().contains(role))
				return true;*/
		/*	
		for (Integer rolePkey: user.getRolepkeys())
			if (getRole(user.getPortalid(), rolePkey).getActionClassNames().contains(action.getClassName()))
			{
			  if (log.isDebugEnabled())
			    log.warn(action.getClassName()+"@"+user.getPortalid()+" granted to "+user.getUserid()+" thanks to role "+rolePkey);
			  return true;
			}*/
		if (action.isAdmin()&&user.isAdmin())
		{
			log.info("Granting Admin access to "+action.getClassName()+" to user "+user.getUserid()+"@"+user.getPortal().getId());
			return true;
		}
/*		if (action.getRoles().size()==0)
		{
			if (log.isDebugEnabled())
				log.warn(action.getClassName()+"@"+user.getPortalid()+" has no active role and is not an UnidentifiedUserAction.");
			return true;
		}*/
		return false;
		//		Set<String> classNames = new HashSet<String>();
		//		for (Role role: user.getRoles())
		//			for (Component component: role.getActions())
		//				classNames.add(component.getClassName());
		//		return classNames.contains(classname);// || classNames.size()==0 Antes se autorizaba si el componente no tenía roles asociados.
		/*
		if (classname==null || classname.length()==0)
			throw new IllegalArgumentException("error.emptyClassName");
		if (userpkey==null)
		{
			log.warn("Null userpkey trying to access "+classname+"; Returning false");
			return false;
		}
	  if (classname.endsWith("UnidentifiedActions"))
	  {
			log.warn("Deprecated fashion unidentified authorization for "+classname);
			return true;
		}
		boolean admin = classname.indexOf("Admin") > -1;
		String servicename = classname.substring(classname.indexOf(".") + 1); // quitamos com
		servicename = servicename.substring(servicename.indexOf(".") + 1); // quitamos servengine/tuportal
		servicename = servicename.substring(0, servicename.indexOf("."));
		return checkServiceaccess(userpkey, servicename, admin);*/
	}

	/**
	 * Devuelve los dos componentes para el servicio. El primero [0] es el de usuario, el segundo, [1] es el de administración.
	 */
	/*	protected Collection<ComponentLocal> getComponentsbyservicename(String servicename, boolean admin) throws FinderException
	{
		Collection<ComponentLocal> components = new ArrayList<ComponentLocal>();
		for (ComponentLocal component: componentlocalhome.findAll())
			if (component.getServiceName().equals(servicename) && component.isAdminclient()==admin)
				components.add(component);
		return components;
	}*/

	/*	public boolean checkServiceaccess(Integer userpkey, String servicename, boolean admin)
	{
		if (servicename.equals("public"))
			return true;
		try
		{
			UserLocal user = userlocalhome.findByPrimaryKey(userpkey);
			if (servicename.equals("system") && !user.isGuestuser())
				return true;
			Collection<ComponentLocal> components = new ArrayList<ComponentLocal>();
			components.addAll(user.getPortal().getComponents());
			components.retainAll(getComponentsbyservicename(servicename,admin));
		  Collection<RoleLocal> componentroles = new ArrayList<RoleLocal>();// Solo los roles comunes a todos los componentes
			if (components.size()==0)
			{
				if (servicename.equals("user"))
					componentroles.add(rolelocalhome.findByRoleid(user.getPortal().getId(),"user"));
				else {
					log.warn("Disabled "+(admin?"admin":"user")+" service: " + servicename + "@" + user.getPortal().getId());
					return false;
				}
			} else
				for (ComponentLocal component: components)
					if (componentroles.size()==0)
						componentroles.addAll(rolelocalhome.findByClassname(user.getPortal().getId(), component.getClassname()));
					else
						componentroles.retainAll(rolelocalhome.findByClassname(user.getPortal().getId(), component.getClassname()));
			if (componentroles.size() == 0)
			{
				if (!admin)
					return true;
				else
				{
					log.warn("Warning: no roles por admin service "+servicename+"; preventing access to "+user.getUserid()+"@"+user.getPortal().getId());
				  return false;
				}
			}
			Collection<RoleLocal> userroles = user.getRoles();
			for (RoleLocal componentrole: componentroles)
				if (userroles.contains(componentrole))
					return true;
			log.info("Access to " + servicename + " service for " + user.getUserid() + "@" + user.getPortal().getId() + " not granted");
			return false;
		} catch (FinderException e)
		{
			throw new IllegalArgumentException(e.getMessage(), e);
		}
	}*/

	/**
	 * Returns portal id for this user, after checking it has permissions to access that component.
	 */
	/*	public boolean checkaccess(Integer userpkey, String classname)
	{
		try
		{
			return checkaccess(userlocalhome.findByPrimaryKey(userpkey), classname);
		} catch (FinderException e)
		{
			return false;
		}
	}*/

	/**
	 * Checks if userid has at least one of the roles required by jndiname component.
	 */
	public boolean checkAccess(User user, String classname)
	{
		/*try
		{
			Component component = componentlocalhome.findByPrimaryKey(classname);
			if (component.getServiceName().equals("admin"))
			{
				Iterator it = user.getRoles().iterator();
				while (it.hasNext())
					if (((RoleLocal)it.next()).getId().equals("admin"))
						return true;
			}
		} catch (FinderException e)
		{
			log.warn("No component " + classname + ". Can't allow " + user.getUserid() + "@" + user.getPortal().getId() + " to access it", e);
			return false;
		}*/
		List<Role> componentroles;
		Query query=entityManager.createNamedQuery("Role.findByClassName");
		query.setParameter("portalid", user.getPortal().getId());
		query.setParameter("classname", classname);
		componentroles=query.getResultList();
		if (componentroles.size()==0)
		{
			if (classname.indexOf("Admin")==-1)
				return true; // El componente no requiere ningún role, así que autorizamos a cualquiera.
			log.warn(classname+" has no roles set in "+user.getPortal().getId());
			if (classname.indexOf("GlobalAdminManagerClient")>-1)
				return true; // El propio componente de administración global ya se encarga de comprobar con checkglobalaccess.
			log.warn(classname+" has no roles set. I can't admit it as a guest client");
			return false;
		}

		Collection userroles=user.getRoles();
		Iterator i=componentroles.iterator();
		while (i.hasNext())
			if (userroles.contains(i.next()))
			{
				log.info("Access to "+classname+" for "+user.getUserid()+"@"+user.getPortal().getId()+" granted");
				return true;
			}

		log.info("Access to "+classname+" for "+user.getUserid()+"@"+user.getPortal().getId()+" not granted");
		return false;
	}

	public void removeUser(User user)
	{
		/*		Role adminrole = null;
		try
		{
			adminrole = getAdminRole(portalid);
		} catch (javax.ejb.FinderException e)
		{
			throw new IllegalStateException("No admin role in portal " + portalid);
		}
		if (user.getRoles().contains(adminrole))
			throw new IllegalArgumentException("Can't remove a user with Admin role");*/
		/*		Collection<ExtraUserdata> expurganda = new ArrayList<ExtraUserdata>();
		 expurganda.addAll(user.getExtraUserdata());
		 for (ExtraUserdata datum: expurganda)
		 {
			 datum.setUser(null);
			 datum.setField(null);
			 entityManager.remove(datum);
		 }
		 entityManager.flush();*/
		entityManager.remove(user);
	}

	public void removeUser(String portalid, String userid)
	{
		removeUser(getUser(portalid, userid));
	}

	public void createAdminUsers(Portal portal)
	{
		for (String userid: globalAdminUserids)
		{
			Role adminRole=getAdminRole(portal.getId());
			if (!exists(portal.getId(), userid))
				createAdminUser(portal, userid, null, null, null, null, null);
			else
			{
				User user=getUser(portal.getId(), userid);
				if (!user.getRoles().contains(adminRole))
					user.getRoles().add(adminRole);
			}
		}
	}

	public void createAdminUser(Portal portal, String adminuserid, String adminpassword, String adminfirstname, String adminlastname, String adminlastname2, String adminemail)
	{
		if (exists(portal.getId(), adminuserid))
			throw new IllegalArgumentException();
		User admin=new User(portal, adminuserid); // Creamos el primer administrador
		admin.encodePassword(adminpassword);
		admin.setFirstname(adminfirstname);
		admin.setLastname(adminlastname);
		admin.setLastname2(adminlastname2);
		admin.setEmail(adminemail);
		admin.getRoles().add(getRole(portal.getId(), "admin")); //FIXME Chapuza
		admin.getRoles().add(getRole(portal.getId(), "user")); //FIXME Chapuza
		entityManager.persist(admin);
		return;
	}

	/*	public User createUser(Portal portal, String userid)
	{
		if (exists(portal.getId(),userid))
			throw new IllegalArgumentException();
		User user = new User(portal,userid);
		entityManager.persist(user);
	  entityManager.flush();
		return user;
	}*/

	public User getUser(String portalid, String userid)
	{
		Query query=entityManager.createNamedQuery("User.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", userid.toLowerCase());
		User user=(User)query.getSingleResult();
		//Lo siguiente estaba antes en la clase User como postLoad pero daba por culo un lazy load (¿?)
		Set<String> actionClassNames=new HashSet<String>();
		for (Role role: user.getRoles())
			for (Component action: role.getActions())
				actionClassNames.add(action.getClassName());
		/*for (Component action: user.getPortal().getActions()) //Da Lazy Load
	  {
			Set<Role> actionRoles = new HashSet<Role>();
			for (Role role: user.getPortal().getRoles())
				if (role.getActions().contains(action)) // En la siguiente llamada da NullPointer (¿?)
					actionRoles.add(role);
			if (user.getRoles().containsAll(actionRoles))
				actionClassNames.add(action.getClassName());
		}*/
		user.setActionClassNames(actionClassNames);
		return user;
	}

	/*	public Collection getUserroles(Integer userpkey) throws FinderException
	{
		ArrayList roles = new ArrayList();
		if (userpkey == null)
			return roles;
		Iterator i = userlocalhome.findByPrimaryKey(userpkey).getRoles().iterator();
		while (i.hasNext())
			roles.add(new RoleSBean((RoleLocal)i.next()));
		return roles;
	}*/

	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public User getUser(String portalid, Integer userId)
	{
		User user=entityManager.find(User.class, userId);
		if (!user.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException("Uffffffff... does that user really belong to your portal?");
		return user;
	}

	public boolean hasGuestUser(String portalid)
	{
		try
		{
			getUser(portalid, guestUserid);
			return true;
		} catch (NoResultException e)
		{
			return false;
		}
	}

	public void setGuestUser(Portal portal, boolean value)
	{
		if (value&&!hasGuestUser(portal.getId()))
		{
			entityManager.persist(new User(portal, guestUserid));
			return;
		}
		if (!value&&hasGuestUser(portal.getId()))
			removeUser(portal.getId(), guestUserid);
	}

	/*	public int getUsercount(String portalid) throws FinderException
	{
		int count = portallocalhome.findByPrimaryKey(portalid).getUsers().size();
		if (guestuserid!=null && hasGuestuser(portalid))
			count--;
		return count;
	}*/

	public long getUserCount()
	{
		return (Long)entityManager.createNamedQuery("User.getUserCount").getSingleResult();
	}

	/*	public User getUser(Integer userpkey)
	{
		return entityManager.find(User.class,userpkey);
	}
*/

	public List<User> getUsersByEmail(String email)
	{
		Query query=entityManager.createNamedQuery("User.findByEmail");
		query.setParameter("email", email);
		return query.getResultList();
	}

	/*	public int sendUserswithemaillist(String email) throws MessagingException
	{
		Collection users = getUsersbyemail(email);
		Iterator it = new TreeSet(users).iterator();
		//if (!it.hasNext())
		//	throw new IllegalStateException("Sorry, but no user in 321portal.com has that email");
		String table = "<table><tr><th>Portalid</th><th>userid</th></tr>\n";
		while (it.hasNext())
		{
			UserSBean user = (UserSBean)it.next();
			table +=
					"<tr><td>" + user.getPortalid() + "</td><td><a href=\"http://www.tuportal.com/esp/user?portalid=" + user.getPortalid() +
					"&userid=" + user.getUserid() + "\">" + user.getUserid() + "</a></td></tr>\n";
		}
		table += "</table>";
		Map substitutions = new HashMap();
		substitutions.put("${usertable}", table);
		mailrelay.send("tuportal.com", "info@tuportal.com", email, "usersforemail", substitutions,null);
		return users.size();
	}

	public void sendUseridsByEmail(String portalid, String email) throws MessagingException, FinderException
	{
	  String list = "<ul>\n";
		for (UserLocal user: userlocalhome.findByEmail(email))			
			if (user.getPortal().getId().equals(portalid))
				list += "<li><a href=\"http://www.tuportal.com/esp/user?portalid=" + portalid +
					"&userid=" + user.getUserid() + "\">" + user.getUserid() + "</li>\n";
		list += "</ul>\n";
		Map substitutions = new HashMap();
		substitutions.put("${userlist}", list);
		mailrelay.send(portalid, getPortalManagerLocal().getPortalemail(portalid).toString(), email, "user.useridsByEmail", substitutions,null);
		return;
	}*/

	/*	public int sendLastUserSessions(String portalid, String email, int howmany) throws FinderException
	{
	  Query query = entityManager.createNamedQuery("UserSession.findLast");
	  query.setParameter("portalid",portalid);
		int count = 0;
		Iterator it = usersessionlocalhome.findByPortalid(portalid).iterator();
		ByteArrayOutputStream ba = new ByteArrayOutputStream();
		PrintWriter pr = new PrintWriter(ba);
		while (it.hasNext() && count < howmany)
		{
			UserSessionLocal session = (UserSessionLocal)it.next();
			pr.println(session.getStarttime() + "," + session.getEndtime() + "," + session.getUserid());
			count++;
		}
		pr.close();
		Collection files = new ArrayList();
		String bodytext = "Last " + count + " users sessions in " + portalid + ":\n\n";
		try
		{
			files.add(new AttachmentDataSource("usersessions.txt", "text/plain", new ByteArrayInputStream(ba.toByteArray())));
		} catch (IOException e)
		{
			bodytext = "Exception while generating last user sessions: " + e.getMessage();
		}

		try
		{
			mailrelay.send("info@tuportal.com", email, "Last " + count + " users sessions in " + portalid, bodytext, "", files);
		} catch (javax.mail.MessagingException e)
		{
			throw new IllegalStateException("MessagingException: " + e.getMessage());
		}
		return count;
	}*/

	public List<UserSession> getLastUserSessions()
	{
		return entityManager.createNamedQuery("UserSession.findAll").getResultList();
	}

	public List<UserSession> getLastUserSessions(String portalid)
	{
		Query query=entityManager.createNamedQuery("UserSession.findByPortalid");
		query.setParameter("portalid", portalid);
		return query.getResultList();
	}

	public List<UserSession> getLastUserSessions(String portalid, String userid)
	{
		Query query=entityManager.createNamedQuery("UserSession.findByUserid");
		query.setParameter("portalid", portalid);
		query.setParameter("userid", userid);
		return query.getResultList();
	}

	public List<UserSession> getLastUserSessionsBySearchString(String portalid, String searchstring)
	{
		Query query=entityManager.createNamedQuery("UserSession.findBySearchString");
		query.setParameter("portalid", portalid);
		query.setParameter("searchstring", "%"+searchstring.toLowerCase()+"%");
		return query.getResultList();
	}

	/*	public void setProperty(User user, String propertyid, String propertyvalue) throws CreateException, FinderException
	{
		propertymanagerlocal.setUserproperty(userpkey, propertyid, propertyvalue);
	}

	public String getProperty(Integer userpkey, String propertyid) throws FinderException
	{
		return propertymanagerlocal.getUserproperty(userpkey, propertyid);
	}
*/
	/*	public Collection<Roles> getRoles(String portalid, String[] roleids) throws FinderException
	{
		Collection<RoleSBean> roles = new ArrayList<RoleSBean>();
		if (roleids != null)
			for (String roleid: roleids)
				roles.add(new RoleSBean(rolelocalhome.findByRoleid(portalid, roleid)));
		return roles;
	}

	public Collection<RoleSBean> getRoles(Collection<Integer> rolepkeys) throws FinderException
	{
		Collection<RoleSBean> roles = new ArrayList<RoleSBean>();
		for (Integer pkey: rolepkeys)
			roles.add(new RoleSBean(rolelocalhome.findByPrimaryKey(pkey)));
		return roles;
	}
*/

	public List<User> getLastUsers(String portalid)
	{
		Query query=entityManager.createNamedQuery("User.findByPortalidOrderByCreatedDesc");
		query.setParameter("portalid", portalid);
		return query.getResultList();
	}

	public void persist(Role role)
	{
		if (role.getId()==null)
		{
			if (entityManager.createNamedQuery("Role.findByName").setParameter("portalid",role.getPortal().getId()).setParameter("name",role.getName()).getSingleResult()!=null)
				throw new IllegalArgumentException();
			entityManager.persist(role);
			entityManager.find(Portal.class, role.getPortal().getId()).getRoles().add(role);
			//Acojonante. La linea anterior es por el puto EagerLoad de Roles en Portal. Surrealista.
		} else
			entityManager.merge(role);
		entityManager.flush();
	}

	/*	public Collection<RoleSBean> getRoles(String portalid) throws FinderException
	{
		ArrayList roleids = new ArrayList();
		Iterator i = portallocalhome.findByPrimaryKey(portalid).getRoles().iterator();
		while (i.hasNext())
			roleids.add(new RoleSBean((RoleLocal)i.next()));
		return roleids;
	}
*/

	public void removeRole(String portalid, Integer roleId)
	{
		Role role=entityManager.find(Role.class, roleId);
		if (!role.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException("My very very good friend. That role is not yours...");
		if (role.getName().equals("admin")||role.getName().equals("user"))
			throw new IllegalArgumentException("You can't remove role "+role.getName());
		role.getPortal().getRoles().remove(role);
		entityManager.remove(role);
	}

	public List<User> getNewUsers(String portalid, Date from)
	{
		Query query=entityManager.createNamedQuery("User.findNew");
		query.setParameter("portalid", portalid);
		query.setParameter("from", from);
		return query.getResultList();
	}

	public List<User> findUsers(String queryString)
	{
		return entityManager.createNativeQuery(queryString, User.class).getResultList();
	}

	public void signupConfirmation(User user, String signature) throws SecurityException
	{
		if (!signature.equals(getSignupSignature(user.getPortalid(), user.getUserid())))
			throw new SecurityException();
		try
		{
			setNewuserroles(user);
		} catch (Exception e)
		{
			throw new IllegalArgumentException(e.getMessage(), e);
		}
	}

	private String getSignupSignature(String portalid, String userid)
	{
		String[] values={ portalid, userid };
		return getMessageDigest(values);
	}

	private void setNewuserroles(User user)
	{
		user.setRoles(getNewUserRoles(user.getPortal().getId()));
	}

	/*	public void sendSignupconfirmationrequestmail(UserSBean user) throws MessagingException, FinderException
	{
		Map substitutions = new HashMap();
		substitutions.put("${userid}", user.getUserid());
	  substitutions.put("${homeurl}", user.getPortal().getHomeurl());
		substitutions.put("${authCode}", getSignupsignature(user.getPortalid(), user.getUserid()));
		InternetAddress adminemail = getPortalManagerLocal().getPortalemail(user.getPortalid());
		if (adminemail==null)
			throw new IllegalStateException("error.noAdminEmail");
		mailrelay.send(user.getPortalid(), adminemail.toString(), user.getEmail(),
				"user.signupConfirmationRequest", substitutions,null);
	}*/
	//TODO Añadir campo para todos o alguno

	public Collection<User> getUsersByRoleIds(String portalid, Integer[] roleIds)
	{
		Set<User> users=new HashSet<User>();
		if (roleIds!=null||roleIds.length==0)
			for (Integer roleId: roleIds)
			{
				Role role=entityManager.find(Role.class, roleId);
				if (!role.getPortal().getId().equals(portalid))
					throw new IllegalArgumentException("roledoesnotbelongtoportal");
				users.addAll(role.getUsers());
			}
		else
			users.addAll(entityManager.createNamedQuery("User.findNoRole").getResultList());
		/*			for (User user: userlocalhome.findByPortalidOrderByID(portalid))
				if (user.getRoles().size()==0)
					users.add(user);*/
		return users;
	}

	/*	public Collection<UserSBean> getUsersstartingwith(String portalid, String startingwith, int firstusertoreturn,
		int howmanyuserstoreturn) throws FinderException
	{
		return getUsersDTO(userlocalhome.findByidstartingwith(portalid, startingwith + "%"), firstusertoreturn,
				howmanyuserstoreturn);
	}*/

	/*	private javax.mail.internet.InternetAddress[] getUsersemailaddresses(String portalid) throws FinderException
	{
		String[] strings = getUsersemail(portalid);
		javax.mail.internet.InternetAddress[] addresses = new javax.mail.internet.InternetAddress[strings.length];
		for (int i = 0; i < strings.length; i++)
			try
			{
				addresses[i] = new javax.mail.internet.InternetAddress(strings[i]);
			} catch (javax.mail.internet.AddressException e)
			{
				if (log.isDebugEnabled())
					log.debug("Error in address:" + addresses[i]);
			}
		return addresses;
	}*/

	/*	public String[] getUsersemail(String portalid) throws FinderException
	{
		Collection users = portallocalhome.findByPrimaryKey(portalid).getUsers();
		String[] emails = new String[users.size()];
		Iterator i = users.iterator();
		int j = 0;
		while (i.hasNext())
			emails[j++] = ((UserLocal)i.next()).getEmail();
		return emails;
	}*/

	/*	public Integer storeExtraUserdataField(String portalid, ExtraUserdataFieldSBean field) throws CreateException,FinderException
	{
		ExtraUserdataFieldLocal fieldLocal = field.getPkey()==null ?
		  extrauserdatafieldlocalhome.create(portallocalhome.findByPrimaryKey(portalid), field.getName()):
		  extrauserdatafieldlocalhome.findByPrimaryKey(field.getPkey());
		if (!fieldLocal.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException();
		fieldLocal.setFieldname(field.getName());
		fieldLocal.setOptions(field.getOptions());
		fieldLocal.setPublicfield(field.isPublicfield());
		fieldLocal.setRequired(field.isRequired());
		fieldLocal.setDefaultValue(field.getDefaultValue());
		return fieldLocal.getPkey();
	}
 */
	/*	public boolean checkPassword(User user, String password)
	{
	  try
		{
			return (user.checkEncodedPassword(password));
		}catch (javax.ejb.FinderException e)
		{
			if (log.isDebugEnabled()) log.debug(e.getMessage());
			return false;
		}
	}*/

	public Collection<User> searchUsers(String portalid, Map<String, Object> searchparameters)
	{
		Collection<Collection<User>> foundcollections=new ArrayList<Collection<User>>();


		StringBuffer jbossQL=new StringBuffer();
		//		Date[] dates=new Date[4]; // TODO Just in case dates are supplied.
		jbossQL.append("select u from User u where u.portal.id='"+portalid+"'");
		StringBuffer where=new StringBuffer();

		Calendar createdFrom=GregorianCalendar.getInstance();
		Calendar createdTo=GregorianCalendar.getInstance();
		Calendar lastLoginFrom=GregorianCalendar.getInstance();
		Calendar lastLoginTo=GregorianCalendar.getInstance();

		boolean creationdate=false, lastaccessdate=false;

		for (Map.Entry<String, Object> entry: searchparameters.entrySet()) // TODO quitar el for y hacerlo con contains
		{
			String fieldname=entry.getKey();
			if (fieldname.equals("userid")||fieldname.equals("email")||fieldname.equals("firstname")||fieldname.equals("lastname"))
				if (entry.getValue()!=null&&((String)entry.getValue()).length()>0)
					where.append(" and lcase(u."+fieldname+") like '%"+((String)entry.getValue()).toLowerCase()+"%'");
			if (fieldname.equals("searchString"))
				where.append(" and (lcase(u.userid) like '%"+((String)entry.getValue()).toLowerCase()+"%' or lcase(u.email) like '%"+((String)entry.getValue()).toLowerCase()+"%' or lcase(u.firstname) like '%"+((String)entry.getValue()).toLowerCase()+"%' or lcase(u.lastname) like '%"+((String)entry.getValue()).toLowerCase()+"%' or lcase(u.lastname2) like '%"+((String)entry.getValue()).toLowerCase()+"%')");
			if (fieldname.equals("created"))
			{
				where.append("and (u.created >= :createdFrom and u.created <= :createdTo)");
				createdFrom.setTime((Date)entry.getValue());
				createdTo.setTime(createdFrom.getTime());
				createdTo.add(Calendar.DATE, 1);
				creationdate=true; //TODO quitar al pasar a contains
			}
			if (fieldname.equals("lastLogin"))
			{
				where.append("and (u.lastLogin >= :lastLoginFrom and u.lastLogin <= :lastLoginTo)");
				lastLoginFrom.setTime((Date)entry.getValue());
				lastLoginTo.setTime(lastLoginFrom.getTime());
				lastLoginTo.add(Calendar.DATE, 1);
				lastaccessdate=true; //TODO quitar al pasar a contains
			}
		}
		jbossQL.append(where.toString());
		if (log.isDebugEnabled())
			log.debug(jbossQL);
		Query query=entityManager.createQuery(jbossQL.toString());
		if (creationdate)
		{
			query.setParameter("createdFrom", createdFrom.getTime());
			query.setParameter("createdTo", createdTo.getTime());
		}
		if (lastaccessdate)
		{
			query.setParameter("lastLoginFrom", lastLoginFrom.getTime());
			query.setParameter("lastLoginTo", lastLoginTo.getTime());
		}
		foundcollections.add(query.getResultList());

		if (searchparameters.keySet().contains("roleId"))
		{
			Collection<Integer> roleIds=new ArrayList<Integer>();
			Object roleIdParameter=searchparameters.get("roleId");
			if (roleIdParameter instanceof Integer)
				roleIds.add((Integer)roleIdParameter);
			else if (roleIdParameter instanceof Collection)
				for (Integer roleId: (Collection<Integer>)roleIdParameter)
				{
					if (roleId!=null)
						roleIds.add(roleId);
				}
			else if (roleIdParameter instanceof Integer[])
				for (Integer roleId: (Integer[])roleIdParameter)
				{
					if (roleId!=null)
						roleIds.add(roleId);
				}
			else
				log.warn("Wrong user search parameter roleId of type "+roleIdParameter.getClass().getName());
			for (Integer roleId: roleIds)
			{
				Role role=entityManager.find(Role.class, roleId);
				if (!role.getPortal().getId().equals(portalid))
					throw new IllegalArgumentException();
				foundcollections.add(role.getUsers());
			}
		}

		Collection<User> collection=new ArrayList<User>();
		boolean first=true;
		for (Collection<User> subcollection: foundcollections)
			if (first)
			{
				collection.addAll(subcollection);
				first=false;
			} else
				collection.retainAll(subcollection);
		return collection;
	}


	public String getUsersAsCSV(String portalid)
	{
		StringWriter usersAsCSV=new StringWriter();
		BufferedWriter writer=new BufferedWriter(usersAsCSV);
		TreeSet<ExtraUserdataField> fields=new TreeSet<ExtraUserdataField>();
		Portal portal=entityManager.find(Portal.class, portalid);
		fields.addAll(portal.getExtraUserdataFields());
		try
		{
			for (User user: portal.getUsers())
			{
				writer.write(user.getUserid()+","+user.getFirstname()+","+user.getLastname()+","+user.getLastname2()+","+user.getEmail());
				Map<String, String> extrauserdata=new HashMap<String, String>();
				for (ExtraUserdata datum: user.getExtraUserdata())
					extrauserdata.put(datum.getField().getName(), datum.getValue());
				for (ExtraUserdataField fieldSBean: fields)
					writer.write(","+(extrauserdata.containsKey(fieldSBean.getName())?extrauserdata.get(fieldSBean.getName()):""));
				writer.newLine();
			}
			writer.close();
		} catch (IOException e)
		{
			log.error(e.getMessage(), e);
		}
		return usersAsCSV.toString();
	}

	/*	public void sendSigndownConfirmationMail(User user) throws FinderException,MessagingException
	{
	  Map substitutions = new HashMap();
	  substitutions.put("${userid}", user.getUserid());
	  substitutions.put("${portalid}", user.getPortal().getId());
	  substitutions.put("${homeurl}", user.getPortal().getHomeurl());
	  InternetAddress adminemail = getPortalManagerLocal().getPortalemail(user.getPortalid());
	  if (adminemail==null)
	    throw new IllegalStateException("error.noAdminEmail");
	  mailrelay.send(user.getPortalid(), adminemail.toString(), user.getEmail(), "user.signdownConfirmation", substitutions,null);
	}*/

	/*	public ExtraUserdataFieldSBean getExtraUserdataField(String portalid, Integer pkey) throws FinderException
	{	
		ExtraUserdataFieldLocal field = extrauserdatafieldlocalhome.findByPrimaryKey(pkey);
		if (!field.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException();
		return new ExtraUserdataFieldSBean(field);
	}*/

	/*	public void sendSignupMail(String portalid, Integer id) throws FinderException
	{
		User user = getUser(portalid,id);
		if (isRequiressignupconfirmation(portalid))
			try
			{
				sendSignupconfirmationrequestmail(user);
				//propertymanagerlocal.setUserproperty(userlocal.getPkey(), USER_SIGNUP_CONFIRMATION_PENDING, "true");
			} catch (MessagingException e)
			{
				log.error(e.getMessage(), e);
			}
		else
		{
			InternetAddress portalemail = getPortalManagerLocal().getPortalemail(user.getPortal().getId());
			if (portalemail!=null)
			{
				try
				{
					HashMap subs = new HashMap();
					subs.put("${portalid}",user.getPortal().getId());
					subs.put("${homeurl}",user.getPortal().getHomeurl());
					subs.put("${userid}",user.getUserid());
					subs.put("${firstname}",user.getFirstname()!=null?user.getFirstname():"");
					subs.put("${lastname}",user.getLastname()!=null?user.getLastname():"");
					subs.put("${useremail}",user.getEmail()!=null?user.getEmail():"");
					mailrelay.send(user.getPortal().getId(),portalemail.getAddress(), user.getEmail(), "user.welcome", subs,null);
				} catch (FinderException e)
				{
					log.warn("No user.welcome template. Could not send user welcome message.");
				} catch (MessagingException e)
				{
					log.error(e.getMessage(),e);
				}
				if (user.getPortal().isNewusernotify())
					try
					{
						HashMap subs = new HashMap();
						subs.put("${portalid}",user.getPortal().getId());
						subs.put("${userid}",user.getUserid());
						subs.put("${firstname}",user.getFirstname()!=null?user.getFirstname():"");
						subs.put("${lastname}",user.getLastname()!=null?user.getLastname():"");
						subs.put("${useremail}",user.getEmail()!=null?user.getEmail():"");
						mailrelay.send(user.getPortal().getId(),portalemail.getAddress(),portalemail.getAddress(),"newusernotify.html", subs,null);
					} catch (FinderException e)
					{
						log.warn("No 'newusernotify.html' template. Could not send admin new user message.");
					} catch (MessagingException e)
					{
						log.error(e.getMessage(),e);
					}
				}
			}
	}*/
	// Para authorizeAction, cuando no se sabe el portal, pos si acaso.
	/*	public String getPortalid()
	{
		return getPortalManagerLocal().getPortalid();
	}*/

	/**
	 * @deprecated ServletContextUtils.getMessageDigest
	 * @param inputs
	 * @param content
	 * @return
	 */
	public static String getDigitalSignature(String[] inputs, String content)
	{
		String[] newInputs=new String[inputs.length+1];
		for (int i=0;i<inputs.length;i++)
			newInputs[i]=inputs[i];
		newInputs[inputs.length]=content;
		return getMessageDigest(newInputs);
	}

	public static String getMessageDigest(String input)
	{
		String[] inputs=new String[2];
		inputs[0]=input;
		return getMessageDigest(inputs);
	}

	public static String getMessageDigest(String[] inputs)
	{
		if (inputs.length==0)
			return null;
		try
		{
			MessageDigest sha=MessageDigest.getInstance("SHA-1");
			//for(int n=0;n<values.length;n++)
			for (String input: inputs)
				sha.update(input.getBytes());
			byte[] hash=sha.digest();
			String CPass=new String();
			int h=0;
			String s=new String();
			for (int i=0;i<20;i++)
			{
				h=hash[i]; // Convertir de byte a int
				if (h<0)
					h+=256; // Si son valores negativos, pueden haber problemas de conversi?n.
				s=Integer.toHexString(h); // Devuelve el valor hexadecimal como un String
				if (s.length()<2)
					CPass=CPass.concat("0"); // A?ade un 0 si es necesario
				CPass=CPass.concat(s); // A?ade la conversi?n a la cadena ya existente
			}
			CPass=CPass.toUpperCase(); // Convierte la cadena generada a Mayusculas.
			return CPass;
		} catch (NoSuchAlgorithmException e)
		{
			throw new IllegalStateException(e.getMessage());
		}
	}
	/*	public Collection<User> getUsersWithPropertyId(String portalid, String propertyid) throws FinderException
	{
		ArrayList users = new ArrayList();
		Iterator i = userpropertylocalhome.findByPropertyid(portalid, propertyid).iterator();
		while (i.hasNext())
			users.add(new UserSBean(((UserPropertyLocal)i.next()).getUser()));
		return users;
	}*/

	public Role getRole(String portalid, Integer roleId)
	{
		Role role=entityManager.find(Role.class, roleId);
		if (!role.getPortal().getId().equals(portalid))
			throw new IllegalArgumentException("My very very good friend. That role is not yours...");
		loadRoleLazyData(role);
		return role;
	}

	public Role getRole(String portalid, String name)
	{
		Query query=entityManager.createNamedQuery("Role.findByName");
		query.setParameter("portalid", portalid);
		query.setParameter("name", name);
		Role role=(Role)query.getSingleResult();
		if (role!=null)
			loadRoleLazyData(role);
		return role;
	}
	
	private void loadRoleLazyData(Role role)
	{
	  role.setUserCount((Long)(entityManager.createNamedQuery("Role.getUserCount").setParameter("id", role.getId()).getSingleResult()));
	  role.setActionCount((Long)(entityManager.createNamedQuery("Role.getActionCount").setParameter("id", role.getId()).getSingleResult()));
	  List<String> services = new ArrayList<String>();
	  List<String> adminServices = new ArrayList<String>();
	  for (Component action: role.getActions())
	    if (action.isAdmin())
	      adminServices.add(action.getServiceName());
	    else
	      services.add(action.getServiceName());
	  role.setServices(services.toArray(new String[services.size()]));
	  role.setAdminServices(adminServices.toArray(new String[services.size()]));
	}

	public Set<Role> getRoles(String portalid, Integer[] ids)
	{
		HashSet<Role> roles=new HashSet<Role>();
		if (ids!=null)
			for (Integer id: ids)
				roles.add(getRole(portalid, id));
		return roles;
	}

	public void removeUserPicture(User user)
	{
		user.setPicture(null);
		entityManager.merge(user);
	}

	public User follow(String portalid, Integer userId, String userid)
	{
		User user=getUser(portalid, userId);
		;
		user.getFollowing().add(getUser(portalid, userid));
		persist(user);
		return user;
	}

	public User unFollow(String portalid, Integer userId, String userid)
	{
		User user=getUser(portalid, userId);
		;
		user.getFollowing().remove(getUser(portalid, userid));
		persist(user);
		return user;
	}

	public User acceptFriendship(String portalid, Integer userId, String userid, String signature)
	{
		User user=getUser(portalid, userId);
		;
		User friendshipRequester=getUser(portalid, userid);
		String[] values=new String[2];
		values[0]=""+friendshipRequester.getId();
		values[1]=""+user.getId();
		if (!signature.equals(getMessageDigest(values)))
			throw new IllegalArgumentException();
		user.getFriends().add(friendshipRequester);
		persist(user);
		return user;
	}

	public User destroyFriendship(String portalid, Integer userId, String userid)
	{
		User user=getUser(portalid, userId);
		;
		User friend=getUser(portalid, userid);
		user.getFriends().remove(friend);
		persist(user);
		return user;
	}
}
